<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>在线聊天</title>
    <script src="js/vue.min.js"></script>
    <script src="js/axios.js"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<header class="p900 flexbtw">
    <h3>在线聊天、在线客服</h3>
    <div>
        欢迎 XXX
        <a href="#">退出</a>
    </div>
</header>
<main class="m900 flexbtw">
    <aside>
        <div v-for="i in onlines">{{i}}</div>
    </aside>
    <article>
        <div id="msgs">
            <div v-for="m in messages" :class=" m.id == myid ? 'send' : 'recv' ">
                <label class="user">{{m.id}}</label>
                <span class="msg">
                    <el-image v-if="m.text && m.text.indexOf('img:')==0" :src="m.text.substring(4)"
                         style="max-width: 150px; max-height: 100px"
                          :preview-src-list="[m.text.substring(4)]"
                    >

                    </el-image>
                    <span v-else>{{m.text}}</span>
                </span>
            </div>
        </div>
        <textarea placeholder="Ctrl + Center 发送" id="msg" v-model="text"
            @paste="pasteImg($event)"></textarea>
        <div id="ops">
            <input placeholder="用户名" v-model="myid">
            <button @click="conn">连接</button>
            <input type="file" @change="sendImg" accept="image/*" id="file"
                    style="display: none">
            <button @click="openFileDlg">发送图片</button>
            <button @click="send">发送</button>
        </div>
    </article>
</main>
<script>
    var v  = new Vue({
        el : "main",
        data : {
            myid : "",
            text : "",
            onlines : [],    // 在线人数
            messages : [],   //  接收的所有消息
            websocket : null
        },
        methods : {
            conn(){
                if (!this.myid){
                    alert('请输入用户名');
                    return;
                }
                this.websocket = new WebSocket("ws://127.0.0.1:8080/mysocket/" + this.myid);
                this.websocket.onopen = function (){console.info("open!")}
                this.websocket.onclose = function (){console.info("close!")}
                this.websocket.onerror = function (){console.info("error!")}
                this.websocket.onmessage = (event)=>{
                    // json 字符串 => js 对象
                    var message = JSON.parse(event.data);
                    this.onlines = message.onlines;
                    // 将当前消息保存到 信息数组中
                    // Cannot read properties of undefined (reading 'push')
                    // this ==> WebSocket
                    this.messages.push(message);
                }
        },
            send(){
                this.websocket.send(this.text);
                this.text = "";
            },
            openFileDlg(){
                file.click();  // 触发文件选择框点击事件
            },
            sendImg(){
                if ( file.files == 0){
                    alert("请选择上传的图片");
                    return;
                }
                // 上传图片 => 返回图片地址
                var fd = new FormData();
                fd.append("file", file.files[0]);
                axios.post("upload", fd).then(res=>{
                    //console.info(res);
                    var text = "img:" + res.data.data
                    this.websocket.send(text);
                });
                // 发送消息（图片地址）
                // 客户端接收到图片消息，渲染图片
            },
            pasteImg(e){
                // 获取剪贴板数据
                var clipboard = e.clipboardData;
                // 判断剪贴板的数据是否是图片
                if (clipboard.items[0].type.match(/image/)){
                    let fd = new FormData();
                    // 获取剪贴板的图片
                    let blob = clipboard.items[0].getAsFile();
                    fd.append("file",blob);
                    axios.post("upload",fd).then(res=>{
                        //console.info(res);
                        var text = "img:" + res.data.data
                        this.websocket.send(text);
                    })
                }
            }
        }
    })
</script>
<footer>源辰公司</footer>
</body>
</html>



















































<style>
    * {
        padding: 0px;
        margin: 0px;
        font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif;
    }

    html,body{
        height: 100%;
    }
    body{
        display: flex;
        flex-direction: column;
    }

    a {
        text-decoration: none;
    }

    button{
        padding: 3px 10px;
    }

    .p900 {
        padding: 0px calc((100% - 900px) / 2);
    }

    .m900 {
        width: 900px;
        margin: 0px auto;
    }

    .flexbtw {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    header {
        background-color: #eee;
        flex: none;
    }
    header>h3{
        margin: 10px 0px;
    }

    main {
        flex: auto;
        background-color: #ddd;
    }

    footer {
        flex: none;
        padding: 5px;
        text-align: center;
        background-color: #eee;
    }

    aside {
        width: 200px;
        height: 100%;
        background-color: #ccc;
        flex: none;
    }

    article {
        height: 100%;
        flex: auto;
    }

    article {
        display: flex;
        flex-direction: column;
    }

    #msgs {
        flex: auto;
        box-sizing: border-box;
        padding: 10px;
    }

    #msg {
        flex: none;
        width: 100%;
        height: 100px;
        box-sizing: border-box;
    }

    .send > * {
        float: right;
    }

    .recv > * {
        float: left;
    }

    .send, .recv {
        clear: both;
        padding: 5px 0px;
    }

    .user, .msg {
        padding: 5px;
    }

    .msg {
        background-color: #e9e9e9;
        border-radius: 3px;
    }

    aside>div{
        text-align: center;
        padding: 10px;
        margin: 3px;
        background-color:#8c939d;
    }

    aside>div:hover{
        background-color:#8c939d55;
        cursor: pointer;
    }

    #ops{
        text-align: right;
        padding: 7px;
    }
    #ops>*{
        box-sizing: border-box;
        height: 25px;
        vertical-align: middle;
        margin: 0px 5px;
        text-align: center;
    }
    textarea{
        padding: 3px;
    }
</style>